package com.darwin.darwinUI.core
{
	import com.darwin.darwinUI.containers.ILayer;
	import com.darwin.darwinUI.events.UIEvent;
	import com.darwin.darwinUI.layout.LocateRect;
	import com.darwin.darwinUI.manager.UIManager;
	import com.darwin.darwinUI.uiconst.LocateType;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.Dictionary;
	

	/** 
	 * UI组件基类 
	 * 所有组件必须先添加到显示列表 再进行属性或者子项添加
	 * @author lipi & vanCopper
	 */
	public class UIComponent extends UISprite
	{
		/**
		 *  皮肤对应表
		 */		
		protected var _skinDic:Dictionary = new Dictionary();
		
		private var _sizeChange:Boolean = true;
		
		/**
		 * 组件背景是否改变 
		 */		
		protected var _backgroundChange:Boolean = false;
		
		private var _backgroundAuto:Boolean = true;
		
		public function UIComponent()
		{
			super();
			initUIComponent();
			initDefaultSkin();
		}
		
		protected function onAddToStage(event:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE,onAddToStage);
			
			addEventListener(MouseEvent.CLICK,mouseHandler);
			addEventListener(MouseEvent.MOUSE_DOWN,mouseHandler);
			addEventListener(MouseEvent.MOUSE_UP,mouseHandler);
			addEventListener(MouseEvent.MOUSE_OVER,mouseHandler);
			addEventListener(MouseEvent.MOUSE_OUT,mouseHandler);
			addEventListener(MouseEvent.ROLL_OVER,mouseHandler);
			addEventListener(MouseEvent.ROLL_OUT,mouseHandler);
			
			invalidate();	
			updateDisplayList();
		}
		
		/**
		 * 初始化组件 
		 * 
		 */		
		protected function initUIComponent():void
		{
			addEventListener(Event.RENDER,onRender);
			addEventListener(Event.ADDED_TO_STAGE,onAddToStage);
			invalidate();
		}
		
		/**
		 * 初始化默认皮肤 
		 * 
		 */		
		protected function initDefaultSkin():void
		{
			
		}
		
		public function invalidate():void
		{
			if(this.stage)this.stage.invalidate();
		}
		
		private function onRender(e:Event):void
		{
			updateDisplayList();
		}
		
		/**
		 * 更新显示列表，在显示列表需要重绘时会执行此方法，如果需要程序执行此方法请调 stage.invalidate()方法
		 */
		protected function updateDisplayList():void
		{
			refresh();	
		}
		
		
		private var _name:String;
		/** 
		 * 组件名字，组件名字可用于检索和布局 
		 */
		override public function get name():String
		{
			return _name;
		}
		override public function set name(value:String):void
		{
			_name = value;
		}
		
		private var _autoSize:Boolean = false;
		/**
		 * 组件高宽是否不依照 width height 。此方法在UIComponent不实现，在子类进行实现
		 */
		public function get autoSize():Boolean
		{
			return _autoSize;
		}

		public function set autoSize(value:Boolean):void
		{
			_autoSize = value;
			invalidate();
		}
		
		private var _owner:UIComponent;
		/**
		 * 组件所属的对象
		 */
		public function get owner():UIComponent
		{
			return _owner;
		}

		public function set owner(value:UIComponent):void
		{
			_owner = value;
		}
//	////////////////////////////////////////////////////////////////////////////////////	
//		布局相关属性
		
		private var _locateRect:LocateRect;

		/**
		 * 对象定位矩形，如果此属性被设置，那么在布局容器中将以locateRect来设定位置
		 */
		public function get locateRect():LocateRect
		{
			return _locateRect;
		}

		public function set locateRect(value:LocateRect):void
		{
			_locateRect = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}

		
		protected var _width:Number = 100;
		
		override public function set width(value:Number):void
		{
			_width = value;
			sizeChange = true;
			invalidate();
			
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		override public function get width():Number
		{
			if(backgroundAuto && background)
			{
				_width = background.width;
			}
			return _width;
		}
		
		protected var _height:Number = 100;
		
		override public function set height(value:Number):void
		{
			_height = value;
			sizeChange = true;
			invalidate();
			
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		override public function get height():Number
		{
			if(backgroundAuto && background)
			{
				_height = background.height;
			}
			return _height;
		}
		
		
		private var _horizontalFollowObject:Object;

		/**
		 * 水平线上跟随的对象
		 */
		public function get horizontalFollowObject():Object
		{
			return _horizontalFollowObject;
		}

		public function set horizontalFollowObject(value:Object):void
		{
			_horizontalFollowObject = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}

		private var _verticalFollowObject:Object;

		/**
		 * 垂直线上跟随的对象
		 */
		public function get verticalFollowObject():Object
		{
			return _verticalFollowObject;
		}

		public function set verticalFollowObject(value:Object):void
		{
			_verticalFollowObject = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}

		
		private var _top:Number = Number.NaN;

		/**
		 * 距顶部距离
		 */
		public function get top():Number
		{
			return _top;
		}

		/**
		 * @private
		 */
		public function set top(value:Number):void
		{
			_top = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		private var _left:Number = Number.NaN;

		/**
		 * 距右边距离
		 */
		public function get left():Number
		{
			return _left;
		}

		public function set left(value:Number):void
		{
			_left = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		private var _right:Number = Number.NaN;
		/**
		 * 距右边距离
		 */
		public function get right():Number
		{
			return _right;
		}

		public function set right(value:Number):void
		{
			_right = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		
		private var _bottom:Number = Number.NaN;

		/**
		 * 距底部距离
		 */
		public function get bottom():Number
		{
			return _bottom;
		}

		public function set bottom(value:Number):void
		{
			_bottom = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		
		private var _offsetX:Number = 0;
		/**
		 * 水平居中(horizontalAlign)的偏移,或跟随其它对象时的偏移
		 */
		public function get offsetX():Number
		{
			return _offsetX;
		}

		public function set offsetX(value:Number):void
		{
			_offsetX = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}

		
		
		private var _offsetY:Number = 0;
		/**
		 * 垂直居中(verticalAlign)的偏移,或跟随其它对象时的偏移
		 */
		public function get offsetY():Number
		{
			return _offsetY;
		}

		public function set offsetY(value:Number):void
		{
			_offsetY = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		private var _verticalLocate:String = LocateType.INDEPENDENT;

		public function get verticalLocate():String
		{
			return _verticalLocate;
		}

		public function set verticalLocate(value:String):void
		{
			_verticalLocate = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		
		
		
		private var _horizontalLocate:String = LocateType.INDEPENDENT;

		public function get horizontalLocate():String
		{
			return _horizontalLocate;
		}

		public function set horizontalLocate(value:String):void
		{
			_horizontalLocate = value;
			if(this.owner is ILayer)
			{
				(this.owner as ILayer).updateInform(this);
			}
		}
		

		
//		//////////////////////////////////////////////////////////////////////////////////////////
		

		
		
		private function mouseHandler(event:MouseEvent):void
		{
			switch(event.type)
			{
				case MouseEvent.CLICK:
					onClick();
					break;
				case MouseEvent.MOUSE_DOWN:
					onMouseDown();
					break;
				case MouseEvent.MOUSE_UP:
					onMouseUp();
					break;
				case MouseEvent.MOUSE_OVER:
					onMouseOver();
					break;
				case MouseEvent.MOUSE_OUT:
					onMouseOut();
					break;
				case MouseEvent.ROLL_OVER:
					onRollOver();
					break;
				case MouseEvent.ROLL_OUT:
					onRollOut();
					break;
			}
		}
		
		
		/**
		 * 鼠标是否在当前对象之上 
		 */
		protected var mouseOverStatus:Boolean = false;
		/**
		 * 鼠标是否在当前对象上按下 
		 */
		protected var mouseDownStatus:Boolean = false;
		
		
		public function onMouseOver():void
		{
		}
		public function onMouseOut():void
		{
		}
		public function onMouseDown():void
		{
		}
		public function onMouseUp():void
		{
		}
		
		public function onClick():void
		{
//			UIManager.getToolTipManager().trigger(this,TipsInfo.EVENT_CLICK,this.tipsInfo);
		}
		
		public function onRollOver():void
		{
			mouseOverStatus = true;
			if(tipsData)
			{
				UIManager.getToolTipManager().showTips(null,this,this.tipsData,this.tipsDirection);
			}
		}
		
		public function onRollOut():void
		{
			mouseOverStatus = false;
//			UIManager.getToolTipManager().trigger(this,TipsInfo.EVENT_OUT,this.tipsInfo);
		}
		
		
		private var _tipsData:Object;
		/**
		 * 要显示的tips数据
		 */
		public function get tipsData():Object
		{
			return _tipsData;
		}

		public function set tipsData(value:Object):void
		{
			_tipsData = value;
		}
		
		private var _tipsDirection:String = "up";
		/**
		 * tips方向
		 */
		public function get tipsDirection():String
		{
			return _tipsDirection;
		}

		public function set tipsDirection(value:String):void
		{
			_tipsDirection = value;
		}
		
		
		
//	//////////////////////////////////////////////////////////////////////////////////////////////
		
		protected var _background:DisplayObject;
		/**
		 * 组件背景
		 */
		public function get background():DisplayObject
		{
			return _background;
		}

		public function set background(value:DisplayObject):void
		{
			if(background && background.parent)
			{
				background.parent.removeChild(background);
			}
			_background = value;
			if(_background is DisplayObjectContainer)
			{
				DisplayObjectContainer(_background).mouseEnabled = false;
				DisplayObjectContainer(_background).mouseChildren = false;
			}
			if(_background != null)
			{
				addChildAt(background,0);
			}
			_backgroundChange = true;
			invalidate();
		}
		
		private var _backgroundSkin:String;
		/**
		 * 背景皮肤对象
		 */
		public function get backgroundSkin():String
		{
			return _backgroundSkin;
		}

		public function set backgroundSkin(value:String):void
		{
			_backgroundSkin = value;
			if(value)
			{
				binding(value,"background");
			}else{
				background = null;
			}
		}
	
		/**
		 * 刷新组件 
		 * 
		 */		
		protected function refresh():void
		{
			if((sizeChange || _backgroundChange) && background != null && !backgroundAuto )
			{
				background.width = width;
				background.height = height;
				sizeChange = false;
				_backgroundChange = false;
			}
			
			if((sizeChange || _backgroundChange) && background != null && backgroundAuto )
			{
				width = background.width/background.scaleX;
				height = background.height/background.scaleY;
				sizeChange = false;
				_backgroundChange = false;
			}
			
			if(rectVisible)
			{
				this.graphics.clear();
				this.graphics.lineStyle(1,0xDCDCDC);
				this.graphics.beginFill(0xFFFFFF,.01);
				this.graphics.drawRect(0,0,width,height);
				this.graphics.endFill();
			}
//			
//			if(_backgroundChange && background != null)
//			{
//				_backgroundChange = false;
//				if(width == 0) width = background.width;
//				else background.width = width; 
//				
//				if(height == 0)height = background.height;
//				else background.height = height;
//			}
		}
		
		/**
		 * 将一个皮肤对象名字对应到实际显示对象，
		 * binding负责载入相应的素材并它赋给对应的属性
		 * @param skinName 皮肤属性名
		 * @param bindingName 要绑定的属性名
		 */
		protected function binding(skinName:String,bindingName:String):void
		{
			if(_skinDic[skinName])
			{
				var list:Array = _skinDic[skinName];
				list.push(bindingName);
			}else
			{
				_skinDic[skinName] = [bindingName];
			}
			UISkinProxy.getInstance().getSkin(skinName,skinOnComplete);
		}
		
		/**
		 * 皮肤加载完成 
		 * skinObj = {"aa.cc":child};
		 */		
		protected function skinOnComplete(skinObj:Object):void
		{
			if(skinObj==null){return;};
			
			for (var skinName:String in skinObj) 
			{
				var child:DisplayObject = skinObj[skinName] as DisplayObject;
				if(child)
				{
					var skinList:Array = _skinDic[skinName];
					for (var j:int = 0; j < skinList.length; j++) 
					{
						this[skinList[j]] = child; 
						var uiEvent:UIEvent = new UIEvent(UIEvent.SKIN_COMPLETE,true);
						uiEvent.skinName = skinName;
						dispatchEvent(uiEvent);
					}
				}
			}
		}

		/**
		 * 组件大小是否改变 
		 */
		public function get sizeChange():Boolean
		{
			return _sizeChange;
		}

		/**
		 * @private
		 */
		public function set sizeChange(value:Boolean):void
		{
			_sizeChange = value;
		}

		/**
		 * 组件高宽是否根据背景自动调整
		 * true 组件高宽=背景高宽
		 * false 背景高宽 = 组件设置的高宽 
		 */
		public function get backgroundAuto():Boolean
		{
			return _backgroundAuto;
		}

		/**
		 * @private
		 */
		public function set backgroundAuto(value:Boolean):void
		{
			_backgroundAuto = value;
			_sizeChange = true;
			updateDisplayList();
//			invalidate();
		}
		
		private var _rectViisble:Boolean = false;
		/**
		 * 显示该对象矩形 测试用 
		 * @param vaule
		 * 
		 */		
		public function set rectVisible(vaule:Boolean):void
		{
			_rectViisble = vaule;
			if(_rectViisble == false)
			{
				this.graphics.clear();
			}
			if(this.stage)this.stage.invalidate();
		}
		
		public function get rectVisible():Boolean
		{
			return _rectViisble;
		}


	}
}